package com.ruoyi.water.task;

import com.ruoyi.water.domain.AreaAnalyse;
import com.ruoyi.water.domain.Homepage;
import com.ruoyi.water.service.IAreaAnalyseService;
import com.ruoyi.water.service.IAreaWarnService;
import com.ruoyi.water.service.IHomepageService;
import com.ruoyi.water.service.ILeakageService;
import com.ruoyi.water.service.IMeterAnalyseService;
import com.ruoyi.water.service.IMeterWarnService;
import com.ruoyi.water.service.IPressureTokenService;
import com.ruoyi.water.service.IWaterMeterDataSyncService;
import com.ruoyi.water.service.IHourDataService;
import com.ruoyi.water.service.impl.HourDataServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 水表数据定时同步任务（每天凌晨3点执行）
 * 同步完成后延迟1分钟执行小时数据处理（处理范围：前天+昨天）
 * 小时数据处理完成后，执行前一天（昨天）的水表日分析
 * 最后自动执行数据分析（计算偏差值和同比环比）
 */
@Component
public class DataSyncTask {

    @Autowired
    private IWaterMeterDataSyncService waterMeterDataSyncService;

    @Autowired
    private IHourDataService hourDataService;

    @Autowired
    private IMeterAnalyseService meterAnalyseService;

    // 新增服务注入
    @Autowired
    private IMeterWarnService meterWarnService;

    @Autowired
    private IAreaAnalyseService areaAnalyseService;

    @Autowired
    private IAreaWarnService areaWarnService;

    @Autowired
    private ILeakageService leakageService;

    // 【新增】首页服务注入
    @Autowired
    private IHomepageService homepageService;

    // 【新增】压力Token服务注入
    @Autowired
    private IPressureTokenService pressureTokenService;

    // 时间格式化器（匹配数据库时间字段格式）
    private final SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     * 定时任务核心流程（每天凌晨3点执行）：
     * 1. 同步【昨天】的原始水表数据（00:00:00 ~ 23:59:59）
     * 2. 延迟1分钟，处理【前天+昨天】的小时数据
     * 3. 执行【昨天】的水表日分析
     * 4. 新增：对【昨天】的日数据进行深度分析（计算偏差值和同比环比）
     * 5. 新增流程：生成水表告警 → 区域流量计算 → 区域偏差计算 → 区域告警生成 → 漏耗分析
     * 6. 【新增】计算首页用水趋势 → 同步设备与传感器数据
     */
    @Scheduled(cron = "0 0 3 * * ?")
    // @Scheduled(cron = "0 */1 * * * ?")// 测试用：每分钟执行一次
    public void syncYesterdayMeterDataAndProcessHourData() {
        Date syncStartTime = null;    // 原始数据同步开始时间（昨天00:00）
        Date syncEndTime = null;      // 原始数据同步结束时间（昨天23:59）
        Date processStartTime = null; // 小时数据处理开始时间（前天00:00）
        Date processEndTime = null;   // 小时数据处理结束时间（昨天23:59）
        Date analyseTargetDate = null;// 日分析目标日期（昨天）

        try {
            // ===================== 1. 计算所有时间范围 =====================
            Calendar calendar = Calendar.getInstance();
            // --- 计算“昨天”的时间范围 ---
            calendar.add(Calendar.DAY_OF_MONTH, -1); // 切换到“昨天”
            analyseTargetDate = calendar.getTime();

            // 昨天 00:00:00
            calendar.set(Calendar.HOUR_OF_DAY, 0);
            calendar.set(Calendar.MINUTE, 0);
            calendar.set(Calendar.SECOND, 0);
            syncStartTime = calendar.getTime();

            // 昨天 23:59:59
            calendar.set(Calendar.HOUR_OF_DAY, 23);
            calendar.set(Calendar.MINUTE, 59);
            calendar.set(Calendar.SECOND, 59);
            syncEndTime = calendar.getTime();

            // --- 计算“前天+昨天”的时间范围 ---
            Calendar processCalendar = Calendar.getInstance();
            processCalendar.add(Calendar.DAY_OF_MONTH, -2); // 切换到“前天”
            processCalendar.set(Calendar.HOUR_OF_DAY, 0);
            processCalendar.set(Calendar.MINUTE, 0);
            processCalendar.set(Calendar.SECOND, 0);
            processStartTime = processCalendar.getTime();

            processCalendar.add(Calendar.DAY_OF_MONTH, 2);
            processCalendar.set(Calendar.HOUR_OF_DAY, 23);
            processCalendar.set(Calendar.MINUTE, 59);
            processCalendar.set(Calendar.SECOND, 59);
            processEndTime = processCalendar.getTime();

            // ===================== 2. 同步昨天的原始水表数据 =====================
            System.out.println("===== 开始同步昨天水表原始数据 =====");
            System.out.println("同步时间范围：" + dateFormatter.format(syncStartTime) + " ~ " + dateFormatter.format(syncEndTime));
            int syncCount = waterMeterDataSyncService.syncMeterData(syncStartTime, syncEndTime);
            System.out.println("水表原始数据同步完成，共插入/更新 " + syncCount + " 条记录");

            // ===================== 3. 延迟1分钟等待数据写入 =====================
            System.out.println("===== 等待1分钟后处理小时数据 =====");
            Thread.sleep(60 * 1000);

            // ===================== 4. 处理“前天+昨天”的小时数据 =====================
            System.out.println("===== 开始执行小时数据处理 =====");
            System.out.println("处理时间范围：" + dateFormatter.format(processStartTime) + " ~ " + dateFormatter.format(processEndTime));
            HourDataServiceImpl.HourDataProcessResult processResult = hourDataService.processHourData(
                    dateFormatter.format(processStartTime),
                    dateFormatter.format(processEndTime)
            );
            System.out.println("小时数据处理结果：" +
                    "待插入=" + processResult.getTotalToSave() + "条，" +
                    "实际插入=" + processResult.getActualInserted() + "条，" +
                    "忽略重复=" + processResult.getDuplicateCount() + "条");

            // ===================== 5. 延迟1分钟等待数据写入 =====================
            System.out.println("===== 等待1分钟后执行日分析 =====");
            Thread.sleep(60 * 1000);

            // ===================== 6. 执行“昨天”的水表日分析 =====================
            System.out.println("===== 开始执行昨天水表日分析 =====");
            System.out.println("分析数据范围：" + dateFormatter.format(syncStartTime) + " ~ " + dateFormatter.format(syncEndTime));
            int analysedCount = meterAnalyseService.calculateAndSaveDailyData(syncStartTime, syncEndTime);
            System.out.println("水表日分析完成，共处理 " + analysedCount + " 条记录");

            // ===================== 7. 执行“昨天”的数据深度分析（偏差值+同比环比） =====================
            System.out.println("===== 开始执行昨天数据深度分析 =====");
            System.out.println("分析数据范围：" + dateFormatter.format(syncStartTime) + " ~ " + dateFormatter.format(syncEndTime));
            int deepAnalyseCount = meterAnalyseService.analyzeAndUpdateMeterData(syncStartTime, syncEndTime);
            System.out.println("数据深度分析完成，共计算 " + deepAnalyseCount + " 条记录的偏差值和同比环比");

            // ===================== 8. 延迟1分钟等待数据准备 =====================
            System.out.println("===== 等待1分钟后执行告警及分析流程 =====");
            Thread.sleep(60 * 1000);

            // ===================== 9. 生成水表告警 =====================
            System.out.println("===== 开始生成昨天水表告警 =====");
            System.out.println("告警时间范围：" + dateFormatter.format(syncStartTime) + " ~ " + dateFormatter.format(syncEndTime));
            meterWarnService.generateMeterWarnings(syncStartTime, syncEndTime);
            System.out.println("水表告警生成完成");

            // ===================== 10. 计算区域日流量 =====================
            System.out.println("===== 开始计算区域日流量 =====");
            System.out.println("计算时间范围：" + dateFormatter.format(syncStartTime) + " ~ " + dateFormatter.format(syncEndTime));
            List<AreaAnalyse> dailyFlowList = areaAnalyseService.calculateAreaDailyFlow(syncStartTime, syncEndTime);
            System.out.println("区域日流量计算完成，共处理 " + dailyFlowList.size() + " 条记录");

            // ===================== 11. 计算区域偏差数据 =====================
            System.out.println("===== 开始计算区域偏差数据 =====");
            System.out.println("计算时间范围：" + dateFormatter.format(syncStartTime) + " ~ " + dateFormatter.format(syncEndTime));
            List<AreaAnalyse> biasDataList = areaAnalyseService.calculateAreaBiasData(syncStartTime, syncEndTime);
            System.out.println("区域偏差数据计算完成，共处理 " + biasDataList.size() + " 条记录");

            // ===================== 12. 生成区域告警 =====================
            System.out.println("===== 开始生成区域告警 =====");
            // Date转LocalDate（使用系统默认时区）
            LocalDate startLocalDate = syncStartTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            LocalDate endLocalDate = syncEndTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            System.out.println("告警时间范围：" + startLocalDate + " ~ " + endLocalDate);
            boolean areaWarnResult = areaWarnService.generateAreaWarnByDateRange(startLocalDate, endLocalDate);
            System.out.println("区域告警生成" + (areaWarnResult ? "成功" : "失败"));

            // ===================== 13. 计算漏耗数据 =====================
            System.out.println("===== 开始计算漏耗数据 =====");
            System.out.println("计算时间范围：" + dateFormatter.format(syncStartTime) + " ~ " + dateFormatter.format(syncEndTime));
            int leakageCount = leakageService.calculateLeakageByDateRange(syncStartTime, syncEndTime);
            System.out.println("漏耗数据计算完成，共处理 " + leakageCount + " 条记录");

            // ===================== 14. 【新增】计算首页用水趋势 =====================
            System.out.println("===== 开始计算首页用水趋势 =====");
            homepageService.calculateHomepage();
            System.out.println("首页用水趋势计算完成");

            // ===================== 15. 【新增】同步设备与传感器数据 =====================
            System.out.println("===== 开始同步设备与传感器数据 =====");
            pressureTokenService.syncAllDeviceAndSensorData();
            System.out.println("设备与传感器数据同步完成");

            // ===================== 16. 最终延迟等待（原14序号调整） =====================
            System.out.println("===== 等待1分钟后完成所有流程 =====");
            Thread.sleep(60 * 1000);

        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            System.err.println("===== 定时任务被中断 =====");
            printErrorContext(syncStartTime, syncEndTime, processStartTime, processEndTime, analyseTargetDate);
            System.err.println("中断原因：" + e.getMessage());
        } catch (Exception e) {
            System.err.println("===== 水表数据处理流程失败 =====");
            printErrorContext(syncStartTime, syncEndTime, processStartTime, processEndTime, analyseTargetDate);
            System.err.println("失败原因：" + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 打印错误上下文信息
     */
    private void printErrorContext(Date syncStart, Date syncEnd, Date processStart, Date processEnd, Date analyseDate) {
        System.err.println("【错误上下文】");
        System.err.println("原始数据同步范围：" + (syncStart != null ? dateFormatter.format(syncStart) : "未知") +
                " ~ " + (syncEnd != null ? dateFormatter.format(syncEnd) : "未知"));
        System.err.println("小时数据处理范围：" + (processStart != null ? dateFormatter.format(processStart) : "未知") +
                " ~ " + (processEnd != null ? dateFormatter.format(processEnd) : "未知"));
        System.err.println("分析目标日期：" + (analyseDate != null ? dateFormatter.format(analyseDate) : "未知"));
    }
}